﻿//+-------------------------------------------------------------------------------------------------------------------------------------------------------
//
//Description: ViewDefSectionViewModel
//Author: Aravind Ramarathinam (aravr@microsoft.com)
//
//Copyright © Microsoft Corporation
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
//You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
//
//THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
//INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. 
//See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.
// 
//--------------------------------------------------------------------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using VmroleAuthor.Models;

namespace VmroleAuthor.ViewModels
{
    public class ViewDefSectionViewModel : TreeViewItemViewModel, IDataErrorInfo, IProduceValidationResults, IAddViewDefCategory, IRemoveChildItem, ICanBeRemovedFromTree
    {
        public const string VMSettingsDefaultValue = "VM Settings";
        public const string ApplicationSettingsDefaultValue = "Application Settings";

        public const string VMSettingsAutoCreatedByToolMoniker = "VM Settings AutoCreatedByToolMoniker";
        public const string ApplicationSettingsAutoCreatedByToolMoniker = "Application Settings AutoCreatedByToolMoniker";

        private readonly ViewDefSection viewDefSection;
        private readonly ViewDefViewModel viewDefViewModel;
        private readonly VmRoleResourceDefinitionViewModel resourceDefinitionViewModel;

        private readonly ObservableCollection<ViewDefCategoryViewModel> initialLoadedViewDefCategoryViewModels = new ObservableCollection<ViewDefCategoryViewModel>();
        

        private ViewDefParameterLocalizablePropertyViewModel title;    

        private static class PropertyNames
        {
            public const string Summary = "Summary";
            public const string Title = "Title";
            public const string ViewDefSection = "ViewDefSection";
        }

        public ViewDefSectionViewModel(ViewDefSection viewDefSection, ViewDefViewModel viewDefViewModel, VmRoleResourceDefinitionViewModel resourceDefinitionViewModel)
            : base(viewDefViewModel, true)
        {
            if (viewDefSection == null)
            {
                viewDefSection = new ViewDefSection();
            }
            this.viewDefSection = viewDefSection;
            this.viewDefViewModel = viewDefViewModel;
            this.resourceDefinitionViewModel = resourceDefinitionViewModel;          
            if (this.viewDefSection == null)
            {
                this.viewDefSection = new ViewDefSection();
            }                      
            this.ValidationResults = new ObservableCollection<CloudServiceModelValidationResult>();

            if (!string.IsNullOrEmpty(viewDefSection.Title))
            {
                if (string.Equals(viewDefSection.Title, VMSettingsAutoCreatedByToolMoniker, StringComparison.Ordinal))
                {
                    this.IsThisVMSettingsAutoCreatedByTool = true;
                }
                else if (string.Equals(viewDefSection.Title, ApplicationSettingsAutoCreatedByToolMoniker, StringComparison.Ordinal))
                {
                    this.IsThisApplicationSettingsAutoCreatedByTool = true;
                }
            }
            
            if (this.resourceDefinitionViewModel.IsNewResdefCreatedByTheTool)
            {
                this.Title.PropertyValue = ViewDefViewModel.AutoLocalizeMoniker;
            }

            if (this.viewDefSection.Categories != null)
            {
                foreach (ViewDefCategory viewDefCategory in this.viewDefSection.Categories)
                {
                    this.initialLoadedViewDefCategoryViewModels.Add(new ViewDefCategoryViewModel(viewDefCategory, this, this.viewDefViewModel, this.resourceDefinitionViewModel));
                }
            }                                       
        }

        public bool IsThisVMSettingsAutoCreatedByTool { get; private set; }

        public bool IsThisApplicationSettingsAutoCreatedByTool { get; private set; }

        public ObservableCollection<ViewDefCategoryViewModel> InitialLoadedCategoryViewModels
        {
            get { return this.initialLoadedViewDefCategoryViewModels; }
        }

        public string Summary
        {
            get
            {                      
                return "Section " + (this.Title.PropertyValue??string.Empty) ;
            }
        }

        public ViewDefSection ViewDefSection
        {
            get { return this.viewDefSection; }
        }

        public ViewDefParameterLocalizablePropertyViewModel Title
        {
            get
            {
                if (this.title == null)
                {
                    Func<string> paramValueGetter = () => this.viewDefSection.Title;
                    Action<string> paramValueSetter = delegate(string value)
                        {
                            this.viewDefSection.Title = value;
                            this.OnPropertyChanged(PropertyNames.Summary);
                        };
                    Func<string> autoParamNameGetter = () =>
                        {
                            if (this.IsThisVMSettingsAutoCreatedByTool)
                            {
                                return this.resourceDefinitionViewModel.Name + "VMSettings" + PropertyNames.Title;
                            }
                            if (this.IsThisApplicationSettingsAutoCreatedByTool)
                            {
                                return this.resourceDefinitionViewModel.Name + "ApplicationSettings" + PropertyNames.Title;
                            }
                            return this.resourceDefinitionViewModel.Name + PropertyNames.Title;
                        };
                   
                    Func<string> someInitialValue = () =>
                        {
                            if (this.IsThisVMSettingsAutoCreatedByTool || (this.viewDefSection.Title != null && this.viewDefSection.Title.IndexOf("VMSettings", StringComparison.OrdinalIgnoreCase) >= 0))
                            {
                                return VMSettingsDefaultValue;
                            }
                            if (this.IsThisApplicationSettingsAutoCreatedByTool || (this.viewDefSection.Title != null && this.viewDefSection.Title.IndexOf("ApplicationSettings", StringComparison.OrdinalIgnoreCase) >= 0))
                            {
                                return ApplicationSettingsDefaultValue;
                            }
                            return "VMRoleSectionSettings";
                        };


                    this.title = new ViewDefParameterLocalizablePropertyViewModel(
                        PropertyNames.Title,
                        paramValueGetter,
                        paramValueSetter,
                        autoParamNameGetter,
                        this.viewDefViewModel,
                        true,
                        someInitialValue);
                }
                return this.title;
            }
        }

        public bool CanAddViewDefCategory
        {
            get
            {
                return true;
            }
        }

        public void AddViewDefCategory()
        {
            this.IsExpanded = true; //critical to be done first            
            Debug.Assert(this.viewDefSection!= null);
            ViewDefCategory viewDefCategory = new ViewDefCategory();          
            if (this.viewDefSection.Categories == null)
            {
                this.viewDefSection.Categories = new List<ViewDefCategory>();
            }
            this.viewDefSection.Categories.Add(viewDefCategory);
            var categoryViewModel = new ViewDefCategoryViewModel(viewDefCategory, this, this.viewDefViewModel, this.resourceDefinitionViewModel);
            this.Children.Add(categoryViewModel);
            categoryViewModel.IsSelected = true;
        }

        protected override sealed void LoadChildren()
        {           
            // Load categories
            foreach (ViewDefCategoryViewModel initialLoadedViewDefCategoryViewModel in this.initialLoadedViewDefCategoryViewModels)
            {
                this.Children.Add(initialLoadedViewDefCategoryViewModel);
            }          
        }

        public void RemoveChild(TreeViewItemViewModel childItem)
        {
            var categoryViewModel = childItem as ViewDefCategoryViewModel;
            if (categoryViewModel != null)
            {
                categoryViewModel.Cleanup();
                if (this.viewDefSection.Categories != null)
                {
                    this.viewDefSection.Categories.Remove(categoryViewModel.ViewDefCategory);
                }
                this.Children.Remove(childItem);
            }
        }

        public void Cleanup()
        {
            this.IsExpanded = true;
            ParametersAndPayloadCleanupHelper.CleanupParametersAndPayload(this, typeof(PropertyNames));
        }
        

        public string this[string propertyName]
        {
            get
            {
                string error = null;
                switch (propertyName)
                {
                    case PropertyNames.ViewDefSection:
                        if (this.viewDefSection.Categories == null || this.viewDefSection.Categories.Count == 0)
                        {
                            error = "Need to have atleast one ViewDef Category under this ViewDef section";
                        }                    
                        break;
                }
                return error;              
            }
        }

        public string Error { get; set; }

        public ObservableCollection<CloudServiceModelValidationResult> ValidationResults { get; private set; }

        public void UpdateValidationResults()
        {
            this.IsExpanded = true;
            ModelValidationResultsHelper.UpdateValidationResults(this, typeof(PropertyNames));
            //Add any other cross-field validations error           
        }
    }
}
